home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
130 MIDI Tool Box
/
130 MIDI Tool Box.iso
/
midimod1
/
textwin.c
< prev
next >
Wrap
Text File
|
1993-04-10
|
14KB
|
603 lines
/*
* TEXTWIN.C - Text-windowing system
* Turbo C 2.0
*
* Description: Provides a simple text-menuing interface. Includes pop-down
* menus, and scrolling windows. To use, set up a main window
* with the MainWindow() function.
* eg. MainWindow("Title", 2, "Files", 'f', "Help", 'h');
*
* Then set the commands and command-numbers for each menu use
* the SetMenu function.
* eg. SetMenu(0, 3, "Open",'o',0, "Close",'c',1, "Quit",'q',2);
* SetMenu(1, 3, "Help",'h',3, "------------",-1,-1, "About",'a',4);
*
* Now just make a call to Choice() and the number it returns
* will be the command-number of the choice
* eg. If Help|About is chosen, 4 will be returned.
*
* If you want to get the user to select an option from a list
* of options, make an array of strings with the option
* descriptions in them (ensure final element is NULL). The
* element number chosen will be returned (first element = 0)
* after a call to ScrollChoice()
* eg. If the array is a, and the maximum string length is l, make the call
* ScrollChoice("BetterTitle", a, l);
*
* To display test inside a box, call DrawBox() with a NULL-
* terminated array of strings.
* eg. If the array is a, call
* DrawBox(a);
*
* To display text inside a box, and then wait for a key to be
* pressed, set up a NULL-terminated array of strings and call
* the InfoBox() function
* eg. If the array is a, make the call
* InfoBox(a);
*
* If you want to get input as well as print a box, make a call
* to DialogBox(), if nothing is entered, a default string is
* returned
* eg. DialogBox(a, "C:\") would return "C:\" if nothing was entered.
*
*
* Author: Andrew Scott (Adrenalin Software)
*
* Date: 14/3/1993 ver 0.1
*/
#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
/* Maximum number of chars in a menu title */
#define MAXMENUWIDTH 9
/* Maximum number of chars in a menu command */
#define MAXCOMMWIDTH 12
/* Border graphics */
#define CRNRTL '┌'
#define CRNRTR '┐'
#define CRNRBL '└'
#define CRNRBR '┘'
#define HORIBAR '─'
#define VERTBAR '│'
typedef char *string;
struct MenuStruct {
char n[MAXCOMMWIDTH+1]; /* Item name ("" = no items) */
int k; /* Key-press selector (lower case) */
int x; /* Function reference number (-ve = no command) */
};
typedef struct MenuStruct *MenuItem;
struct MenuBar {
char n[MAXMENUWIDTH+1]; /* Menu name ("" = no menus) */
int k; /* Key-press selector (lower case) */
MenuItem m; /* Menu items */
} *Main;
#if 0
string parmlist(string bit, int n)
{
string s, t;
int l;
s = t = (string) malloc(1 + n * (l = strlen(bit)));
while (n--) {
strcpy(t, bit);
t += l;
}
return s;
}
#endif
void MainWindow(string title, int num, ...)
/* Post: Screen is set up with a nice title and num menus */
{
va_list args;
string t;
int i;
struct MenuBar *c;
c = Main = (struct MenuBar *) malloc(sizeof(struct MenuBar) * (num + 1));
va_start(args, &num);
textmode(C80);
textcolor(CYAN);
textbackground(BLACK);
clrscr();
textbackground(BLUE);
textcolor(WHITE);
i = 80 - strlen(title);
cprintf("%*c%s%*c", i/2, ' ', title, i/2 + i%2, ' ');
textcolor(YELLOW);
cprintf(" ");
for (i = num; i--; c++) {
t = (va_arg(args, string));
strcpy(c->n, t);
cprintf("%-*s", MAXMENUWIDTH, t);
c->k = (va_arg(args, int));
c->m = NULL;
}
c->n[0] = 0;
cprintf("%*c", 79 - MAXMENUWIDTH * num, ' ');
va_end(args);
}
void SetMenu(int menu, int n, ...)
/* Post: n commands has been set in menu #menu (0 = 1st) */
{
va_list args;
string t;
struct MenuBar *c1;
MenuItem c2;
int i;
for (i = menu, c1 = Main; i-- && c1->n[0] != 0; c1++);
if (! c1->n[0])
return; /* error */
c1->m = c2 = (MenuItem) malloc(sizeof(struct MenuStruct) * (n + 1));
va_start(args, &n);
for (; n--; c2++) {
t = va_arg(args, string);
strcpy(c2->n, t);
c2->k = va_arg(args, int);
c2->x = va_arg(args, int);
}
c2->n[0] = 0;
}
int _Menulength_; /* ignore this unstructured global variable ;) */
void PrintMenu(MenuItem m, int x)
/* Post: The menu which is pointed to by m is printed at column x */
{
int i;
char t[MAXCOMMWIDTH + 3];
i = MAXCOMMWIDTH+2;
t[i] = 0;
while (i--)
t[i] = HORIBAR;
textcolor(YELLOW);
textbackground(BLUE);
gotoxy(x, 3);
cprintf("%c%s%c", CRNRTL, t, CRNRTR);
_Menulength_ = 2;
i = 4;
while (m->n[0]) {
_Menulength_++;
gotoxy(x, i++);
cprintf("%c %-*s %c", VERTBAR, MAXCOMMWIDTH, (m++)->n, VERTBAR);
}
gotoxy(x, i);
cprintf("%c%s%c", CRNRBL, t, CRNRBR);
}
void ClearMenu(int x)
/* Post: The last menu printed at column x is now gone */
{
int i = 3;
textcolor(CYAN);
textbackground(BLACK);
while (_Menulength_--) {
gotoxy(x, i++);
cprintf("%*c", MAXCOMMWIDTH + 4, ' ');
}
}
void PrintComm(MenuItem m, int x, int y)
/* Post: Item *m is highlighted at column x, position y */
{
gotoxy(x+1, y+4);
textcolor(MAGENTA);
textbackground(BLACK);
cprintf(" %-*s ", MAXCOMMWIDTH, m->n);
}
void ClearComm(MenuItem m, int x, int y)
/* Post: Item *m is normalized at column x, position y */
{
gotoxy(x+1, y+4);
textcolor(YELLOW);
textbackground(BLUE);
cprintf(" %-*s ", MAXCOMMWIDTH, m->n);
}
void PrintBar(string s, int w, int y)
/* Post: String s (width w) is highlighted in the text window on line y */
{
gotoxy(1, y+1);
textcolor(WHITE);
textbackground(BLACK);
cprintf(" %-*s ", w, s);
}
void ClearBar(string s, int w, int y)
/* Post: String s (width w) is normalized in the text window on line y */
{
gotoxy(1, y+1);
textcolor(BLACK);
textbackground(CYAN);
cprintf(" %-*s ", w, s);
}
void Beep()
/* Post: Speaker has made a beep */
{
printf("%c", 7);
}
int Choice()
/*
* Returns: a function reference number corresponding to a chosen command,
* but returns -1 on an error.
*/
{
int ch;
struct MenuBar *c;
MenuItem p, q;
int i, fx = -1, y;
textcolor(CYAN);
textbackground(BLACK);
gotoxy(1, 25);
do {
cprintf("\rPress the letter of the menu you wish to select.");
ch = tolower(getch());
for (c = Main, i = 0; c->n[0] && c->k != ch; c++, i++);
i = 2 + MAXMENUWIDTH * i;
if (c->n[0] != 0)
do {
cprintf("\rPress a letter, or use cursor keys and <RETURN> to select a command.");
gotoxy(i, 2);
textbackground(BLUE);
textcolor(LIGHTRED);
cprintf("%-*s", MAXMENUWIDTH, c->n);
PrintMenu(p = c->m, i);
PrintComm(p, i, y = 0);
do {
ch = tolower(getch());
if (!ch) {
ch = -getch();
if (ch==-72) /* up-arrow */
if (!y)
Beep();
else {
ClearComm(p--, i, y--);
PrintComm(p, i, y);
}
else if (ch==-80) /* down-arrow */
if (! (p+1)->n[0])
Beep();
else {
ClearComm(p++, i, y++);
PrintComm(p, i, y);
}
} else {
for (q = c->m; q->n[0] && q->k != ch; q++);
if (q->n[0])
fx = q->x;
}
} while ((ch==-72 || ch==-80) && fx < 0);
if (ch==13 && fx < 0)
fx = p->x;
ClearMenu(i);
gotoxy(i, 2);
textbackground(BLUE);
textcolor(YELLOW);
cprintf("%-*s", MAXMENUWIDTH, c->n);
textcolor(CYAN);
textbackground(BLACK);
gotoxy(1, 25);
cprintf("%52c", ' ');
if (ch==-75)
if (i==2)
Beep();
else {
i -= MAXMENUWIDTH;
c--;
}
else if (ch==-77)
if (! (c+1)->n[0])
Beep();
else {
i += MAXMENUWIDTH;
c++;
}
} while (ch != 27 && fx < 0);
clreol();
} while (fx < 0);
return fx;
}
void ClearWin()
/* Post: Area below command and title bars is clear */
{
textcolor(CYAN);
textbackground(BLACK);
window(1, 3, 80, 25);
clrscr();
window(1, 1, 80, 25);
}
int ScrollChoice(string title, string *sp, int w)
/*
* Returns: The offset of the string from s which is chosen, -1 on none
* s points to the start of a list of strings, max length w, NULL term.
*/
{
string s, t, *srt, *end;
int l, p, cur, ch, x = -1;
if (strlen(title) > w)
w = strlen(title);
textcolor(CYAN);
textbackground(BLACK);
gotoxy(1, 25);
cprintf("Use cursor keys and <RETURN> to make a selection.");
s = t = (string) malloc(w + 3);
for (p = w+2; p--; *(t++) = HORIBAR);
*t = 0;
gotoxy(5,3);
textcolor(BLACK);
textbackground(CYAN);
cprintf("%c%s%c", CRNRTL, s, CRNRTR);
gotoxy(6 + (w - strlen(title))/2, 3);
cprintf(" %s ", title);
srt = end = sp;
for (end = sp, l = 0; *end!=NULL && l<20; l++) {
gotoxy(5, l+4);
cprintf("%c %-*s %c", VERTBAR, w, *(end++), VERTBAR);
}
end--;
gotoxy(5, l+4);
cprintf("%c%s%c", CRNRBL, s, CRNRBR);
free(s);
window(6, 4, 8+w, l+3);
PrintBar(*srt, w, p = 0);
cur = 0;
x = -1;
do {
ch = tolower(getch());
if (!ch) {
ch = -getch();
if (ch==-72)
if (!cur)
Beep();
else if (p) {
ClearBar(*(srt+p), w, p);
p--;
PrintBar(*(srt+p), w, p);
cur--;
} else {
ClearBar(*(srt--), w, 0);
gotoxy(1, 1);
insline();
gotoxy(w+3, 1);
cprintf("%c", VERTBAR);
PrintBar(*srt, w, 0);
end--;
cur--;
}
else if (ch==-80)
if (p==l-1 && *(end+1)==NULL)
Beep();
else if (p < l-1) {
ClearBar(*(srt+p), w, p);
p++;
cur++;
PrintBar(*(srt+p), w, p);
} else {
ClearBar(*end, w, p);
end++;
gotoxy(w+3, l);
cprintf("%c", VERTBAR); /* argh.. cant print at final corner */
cur++;
PrintBar(*end, w, p);
srt++;
}
} else if (ch==13)
x = cur;
} while (x < 0 && ch != 27);
ClearWin();
return x;
}
void PrintBox(string *sp, int *x1, int *y1, int *w1)
/*
* Post: The NULL-terminated array of strings pointed to by sp is printed,
* and x1, y1 are set to be the co-ordinates of the bottom-left corner,
* w1 is set to be the width of the inside of the box.
*/
{
int w, x, i, j;
string s, t, *c;
if (*sp==NULL)
return;
c = sp;
for (w = strlen(*(c++)), i = 1; *c!=NULL; c++, i++)
if (w < (x = strlen(*c)))
w = x;
*w1 = w + 2;
*x1 = 1 + (x = (76 - w)/2);
i = 3 + (21 - i)/2;
s = t = (string) malloc(w+3);
for (j = w+2; j--; *(t++) = HORIBAR);
*t = 0;
textcolor(BLACK);
textbackground(CYAN);
gotoxy(x, i++);
cprintf("%c%s%c", CRNRTL, s, CRNRTR);
for (c = sp; *c!=NULL; c++) {
gotoxy(x, i++);
cprintf("%c %-*s %c", VERTBAR, w, *c, VERTBAR);
}
*y1 = i-1;
gotoxy(x, i);
cprintf("%c%s%c", CRNRBL, s, CRNRBR);
free(s);
}
void DrawBox(string *sp)
/* Post: The NULL-terminated array of strings pointed to by sp is printed */
{
int i;
PrintBox(sp, &i, &i, &i);
}
char InfoBox(string *sp)
/*
* Returns: The key pressed after the NULL-terminated array of strings
* pointed to by sp is printed.
*/
{
int k;
DrawBox(sp);
textcolor(CYAN);
textbackground(BLACK);
gotoxy(1, 25);
cprintf("Please press a key.");
k = getch();
ClearWin();
return k;
}
string DialogBox(string *sp, string def)
/* Pre: def != NULL */
/*
* Returns: The string entered (or def if none entered), after printing
* box filled with NULL-terminated strings sp.
*/
{
int x, y, w, ch, i=0;
string s;
PrintBox(sp, &x, &y, &w);
s = (string) malloc(w+1);
strcpy(s, def);
textcolor(CYAN);
textbackground(BLACK);
gotoxy(1, 25);
cprintf("Enter text, and when you are finished, press <RETURN>.");
textcolor(WHITE);
gotoxy(x, y);
cprintf("%-*s", w, s);
window(x, y, x+w-1, y);
gotoxy(1, 1);
x = strlen(s);
do {
if (!(ch = getch()))
ch = -getch();
if (ch==8 || ch==127)
if (!i)
Beep();
else {
cprintf("\b");
clreol();
x = --i;
}
else if (ch==-75)
if (!i)
Beep();
else {
cprintf("\b");
i--;
}
else if (ch==-77)
if (i==x)
Beep();
else {
cprintf("%c", s[i]);
i++;
}
else if (ch!=13 && ch!=27)
if (i==w-1)
Beep();
else {
cprintf("%c", ch);
if (i==x)
x++;
s[i++] = ch;
}
} while (ch!=13 && ch!=27);
s[i] = 0;
if (ch==27) {
free(s);
strcpy(s = (string) malloc(strlen(def)+1), def);
}
ClearWin();
return s;
}
/*
* This main function is for testing the basics of these routines.
* Leave it commented out when creating object files.
*
main()
{
string scrolly[] = {
"First one",
"Second option",
"3rd",
"4th",
"Fifth",
"This could go on for AGES",
"Why not stop soon?",
"Ok",
"How about the next one",
"Done",
"Nope",
"Here's another few..",
"Un",
"Deux",
"Trois",
"Quatre",
"When should I stop?",
"Not yet obviously.",
"Cinq",
"Six",
"Sept",
"I think that's enough",
"Well maybe one more.",
NULL
};
string diagbox[] = {
"Please enter some gibberish",
"below at the prompt please.",
"It WONT check your spelling.",
"",
"",
NULL
};
string s;
MainWindow("Big Huge Title", 3, "Ace", 'a', "Bee", 'b', "seaCide", 'c');
SetMenu(0, 3, "First", 'f', 1, "------------", -1, -1, "Second", 's', 2);
SetMenu(1, 1, "Spelling", 's', 3);
SetMenu(2, 2, "I'd like", 'i', 4, "To be beside", 't', 5);
while (1)
switch (Choice()) {
case 1:
ScrollChoice("Window Name", scrolly, 25);
break;
case 3:
s = DialogBox(diagbox, "sample");
free(s);
break;
case 5:
exit(0);
}
}
* Ok.. this ends the commented out part
*/